append_uint16 (output, parent_id);
}
+static void
+append_node (BroadwayOutput *output,
+ BroadwayNode *node)
+{
+ append_uint32 (output, node->type);
+ guint32 i;
+
+ for (i = 0; i < node->n_data; i++)
+ append_uint32 (output, node->data[i]);
+ for (i = 0; i < node->n_children; i++)
+ append_node (output, node->children[i]);
+}
+
+guint32
+get_node_size (BroadwayNode *node)
+{
+ guint32 size = 1 + node->n_data;
+ guint32 i;
+
+ for (i = 0; i < node->n_children; i++)
+ size += get_node_size (node->children[i]);
+
+ return size;
+}
+
+
void
broadway_output_window_set_nodes (BroadwayOutput *output,
int id,
- guint32 *data,
- guint32 data_len)
+ BroadwayNode *root)
{
write_header (output, BROADWAY_OP_SET_NODES);
- guint32 i;
append_uint16 (output, id);
- append_uint32 (output, data_len);
- for (i = 0; i < data_len; i++)
- append_uint32 (output, data[i]);
+ append_uint32 (output, get_node_size (root));
+ append_node (output, root);
}
void
gboolean visible;
gint32 transient_for;
guint32 texture;
- guint32 *nodes;
- gint nodes_len;
+ BroadwayNode *nodes;
};
static void broadway_server_resync_windows (BroadwayServer *server);
G_DEFINE_TYPE (BroadwayServer, broadway_server, G_TYPE_OBJECT)
+static void
+broadway_node_free (BroadwayNode *node)
+{
+ int i;
+ for (i = 0; i < node->n_children; i++)
+ broadway_node_free (node->children[i]);
+
+ g_free (node);
+}
+
+
static void
broadway_server_init (BroadwayServer *server)
{
static void
broadway_window_free (BroadwayWindow *window)
{
- g_free (window->nodes);
+ if (window->nodes)
+ broadway_node_free (window->nodes);
g_free (window);
}
return server->output != NULL;
}
+/* passes ownership of nodes */
void
broadway_server_window_set_nodes (BroadwayServer *server,
gint id,
- gint n_data,
- guint32 *data)
+ BroadwayNode *root)
{
BroadwayWindow *window;
if (window == NULL)
return;
- g_free (window->nodes);
- window->nodes = g_memdup (data, sizeof (guint32)*n_data);
- window->nodes_len = n_data;
+ if (window->nodes)
+ broadway_node_free (window->nodes);
+ window->nodes = root;
if (server->output != NULL)
broadway_output_window_set_nodes (server->output, window->id,
- window->nodes, window->nodes_len);
+ window->nodes);
}
guint32
if (window->nodes)
broadway_output_window_set_nodes (server->output, window->id,
- window->nodes, window->nodes_len);
+ window->nodes);
if (window->visible)
broadway_output_show_surface (server->output, window->id);
#define NODE_SIZE_COLOR_STOP (NODE_SIZE_FLOAT + NODE_SIZE_COLOR)
#define NODE_SIZE_SHADOW (NODE_SIZE_COLOR + 3 * NODE_SIZE_FLOAT)
-static int
-rewrite_node_textures (BroadwayClient *client,
- int len, guint32 data[], int pos)
+static BroadwayNode *
+decode_nodes (BroadwayClient *client,
+ int len, guint32 data[], int *pos)
{
+ BroadwayNode *node;
guint32 type;
- guint32 i, n_children, n_stops, n_shadows;
+ guint32 i, n_stops, n_shadows;
+ guint32 size, n_children;
+ gint32 texture_offset;
- g_assert (pos < len);
+ g_assert (*pos < len);
- type = data[pos++];
+ size = 0;
+ n_children = 0;
+ texture_offset = -1;
+
+ type = data[(*pos)++];
switch (type) {
case BROADWAY_NODE_COLOR:
- pos += NODE_SIZE_RECT + NODE_SIZE_COLOR;
+ size = NODE_SIZE_RECT + NODE_SIZE_COLOR;
break;
case BROADWAY_NODE_BORDER:
- pos += NODE_SIZE_RRECT + 4 * NODE_SIZE_FLOAT + 4 * NODE_SIZE_COLOR;
+ size = NODE_SIZE_RRECT + 4 * NODE_SIZE_FLOAT + 4 * NODE_SIZE_COLOR;
break;
case BROADWAY_NODE_INSET_SHADOW:
case BROADWAY_NODE_OUTSET_SHADOW:
- pos += NODE_SIZE_RRECT + NODE_SIZE_COLOR + 4 * NODE_SIZE_FLOAT;
+ size = NODE_SIZE_RRECT + NODE_SIZE_COLOR + 4 * NODE_SIZE_FLOAT;
break;
case BROADWAY_NODE_TEXTURE:
- data[pos+4] = GPOINTER_TO_INT (g_hash_table_lookup (client->textures,
- GINT_TO_POINTER (data[pos+4])));
- pos += 5;
+ texture_offset = 4;
+ size = 5;
break;
case BROADWAY_NODE_CONTAINER:
- n_children = data[pos++];
- for (i = 0; i < n_children; i++)
- pos = rewrite_node_textures (client, len, data, pos);
+ size = 1;
+ n_children = data[*pos];
break;
case BROADWAY_NODE_ROUNDED_CLIP:
- pos += NODE_SIZE_RRECT;
- pos = rewrite_node_textures (client, len, data, pos);
+ size = NODE_SIZE_RRECT;
+ n_children = 1;
break;
case BROADWAY_NODE_CLIP:
- pos += NODE_SIZE_RECT;
- pos = rewrite_node_textures (client, len, data, pos);
+ size = NODE_SIZE_RECT;
+ n_children = 1;
break;
case BROADWAY_NODE_LINEAR_GRADIENT:
- pos += NODE_SIZE_RECT + 2 * NODE_SIZE_POINT;
- n_stops = data[pos++];
- pos += n_stops * NODE_SIZE_COLOR_STOP;
+ size = NODE_SIZE_RECT + 2 * NODE_SIZE_POINT;
+ n_stops = data[*pos + size++];
+ size += n_stops * NODE_SIZE_COLOR_STOP;
break;
case BROADWAY_NODE_SHADOW:
- n_shadows = data[pos++];
- pos += n_shadows * NODE_SIZE_SHADOW;
- pos = rewrite_node_textures (client, len, data, pos);
+ size = 1;
+ n_shadows = data[*pos];
+ size += n_shadows * NODE_SIZE_SHADOW;
+ n_children = 1;
break;
case BROADWAY_NODE_OPACITY:
- pos += NODE_SIZE_FLOAT;
- pos = rewrite_node_textures (client, len, data, pos);
+ size = NODE_SIZE_FLOAT;
+ n_children = 1;
break;
default:
g_assert_not_reached ();
}
- return pos;
-}
+ node = g_malloc (sizeof(BroadwayNode) + (size - 1) * sizeof(guint32) + n_children * sizeof (BroadwayNode *));
+ node->type = type;
+ node->n_children = n_children;
+ node->children = (BroadwayNode **)((char *)node + sizeof(BroadwayNode) + (size - 1) * sizeof(guint32));
+ node->n_data = size;
+ for (i = 0; i < size; i++)
+ {
+ node->data[i] = data[(*pos)++];
+ if (i == texture_offset)
+ node->data[i] = GPOINTER_TO_INT (g_hash_table_lookup (client->textures,
+ GINT_TO_POINTER (node->data[i])));
+ }
+
+ for (i = 0; i < n_children; i++)
+ node->children[i] = decode_nodes (client, len, data, pos);
+
+ return node;
+}
static void
client_handle_request (BroadwayClient *client,
{
gsize array_size = request->base.size - sizeof (BroadwayRequestSetNodes) + sizeof(guint32);
int n_data = array_size / sizeof(guint32);
+ int pos = 0;
+ BroadwayNode *node;
- rewrite_node_textures (client, n_data, request->set_nodes.data, 0);
+ node = decode_nodes (client, n_data, request->set_nodes.data, &pos);
- broadway_server_window_set_nodes (server,
- request->set_nodes.id,
- n_data,
- request->set_nodes.data);
+ broadway_server_window_set_nodes (server, request->set_nodes.id,
+ node);
}
break;
case BROADWAY_REQUEST_UPLOAD_TEXTURE: